package top.beiermode.geektime.projects.user.sql;

import org.apache.commons.lang.ClassUtils;
import top.beiermode.geektime.projects.user.domain.User;
import top.beiermode.geektime.projects.user.repository.DataBaseUserRepository;

import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.sql.DataSource;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * 数据库链接管理
 *
 * @author Chen Song
 * @since 1.0
 */
public class DBConnectionManager {

    private final Logger logger = Logger.getLogger(DBConnectionManager.class.getName());

    @Resource(name = "bean/UserPlatformDB")
    private DataSource dataSource;

    @Resource(name = "bean/EntityManager")
    private EntityManager entityManager;

    public EntityManager getEntityManager() {
        logger.info("当前 EntityManager 实现类：" + entityManager.getClass().getName());
        return entityManager;
    }

    public Connection getConnection() {
        Connection connection = null;
        try {
            connection = dataSource.getConnection();
        } catch (SQLException e) {
            logger.log(Level.SEVERE, e.getMessage());
        }
        if (connection != null) {
            logger.log(Level.INFO, "获取 JNDI 数据库连接成功！");
        }
        return connection;
    }

    public void ReleaseConnection() {

    }



    // === Test ===
    public static final String DROP_USERS_TABLE_DDL_SQL = "DROP TABLE users";

    public static final String CREATE_USERS_TABLE_DDL_SQL = "CREATE TABLE users(" +
            "id INT NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1), " +
            "name VARCHAR(16) NOT NULL, " +
            "password VARCHAR(64) NOT NULL, " +
            "email VARCHAR(64) NOT NULL, " +
            "phoneNumber VARCHAR(64) NOT NULL" +
            ")";

    public static final String INSERT_USER_DML_SQL = "INSERT INTO users(name,password,email,phoneNumber) VALUES " +
            "('A','******','a@gmail.com','1') , " +
            "('B','******','b@gmail.com','2') , " +
            "('C','******','c@gmail.com','3') , " +
            "('D','******','d@gmail.com','4') , " +
            "('E','******','e@gmail.com','5')";

    public static final String GET_ALL_SQL = "select id,name,password,email,phoneNumber FROM users";


    public static void main(String[] args) throws Exception {
        String databaseURL = "jdbc:derby:db/user-platform;create=true";
        Connection connection = DriverManager.getConnection(databaseURL);
        Statement statement = connection.createStatement();

        // 删除 users 表
        System.out.println(statement.execute(DROP_USERS_TABLE_DDL_SQL)); // false
        // 创建 users 表
        System.out.println(statement.execute(CREATE_USERS_TABLE_DDL_SQL)); // false
        // 插入 5 条测试数据
        System.out.println(statement.executeUpdate(INSERT_USER_DML_SQL));  // 5

        PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO users(name,password,email,phoneNumber) VALUES (?,?,?,?)");

        /*preparedStatement.setString(1, "张三");
        preparedStatement.setString(2, "123456");
        preparedStatement.setString(3, "1@1");
        preparedStatement.setString(4, "6");*/

        Object[] params = {"张三", "123456", "1@1", "6"};
        for (int i = 0; i < params.length; i++) {
            Object arg = params[i];
            Class argType = arg.getClass();

            Class primitiveType = ClassUtils.wrapperToPrimitive(argType);
            if (primitiveType == null) {
                primitiveType = argType;
            }

            String methodName = DataBaseUserRepository.preparedStatementMethodMappings.get(argType);
            Method method = PreparedStatement.class.getMethod(methodName, int.class, primitiveType);
            method.invoke(preparedStatement, i + 1, arg);
        }
        System.out.println(preparedStatement.executeUpdate());


        // 获取 users
        ResultSet resultSet = statement.executeQuery(GET_ALL_SQL);
        BeanInfo beanInfo = Introspector.getBeanInfo(User.class, Object.class);
        List<User> users = new ArrayList<>();
        while (resultSet.next()) {
            User user = new User();
            for (PropertyDescriptor propertyDescriptor : beanInfo.getPropertyDescriptors()) {
                String fieldName = propertyDescriptor.getName();
                Class fieldType = propertyDescriptor.getPropertyType();
                String methodName = DataBaseUserRepository.resultSetMethodMappings.get(fieldType);
                String columnLabel = fieldName;
                // 调用 getXXX 方法
                Method resultSetMethod = ResultSet.class.getMethod(methodName, String.class);
                Object resultValue = resultSetMethod.invoke(resultSet, columnLabel);
                // 调用 user setXXX 方法
                Method setterMethodFromUser = propertyDescriptor.getWriteMethod();
                setterMethodFromUser.invoke(user, resultValue);
            }
            users.add(user);
        }
        System.out.println(users);
    }
}
